/*
 * CS_GET_MATCH_RESULT.cpp
 *
 *  Created on: 2013. 9. 26.
 *      Author: mega@gamevil.com
 */

#include "../../Command.h"

#include "../../User.h"
#include "../../Proxy.h"
#include "../../GameLog.h"

#include "../../NLogic/Bag.h"
#include "../../NLogic/Item.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Party.h"
#include "../../NLogic/Score.h"
#include "../../NLogic/BattleResult.h"
#include "../../NLogic/Function.h"
#include "../../NLogic/Battle.h"
#include "../../NLogic/DailyMission.h"
#include "../../NResource/Static.h"
#include "../../NGameLog/Static.h"


namespace ProjectZ { namespace NCommand {

void SendPacket_CS_GET_MATCH_RESULT(User * pUser, NLogic::Space * pSpace, int res, int winPoint, int evolvePoint, uint64_t itemSeq, int bagType)
{

	User * pWinUser = NULL;

	if (pSpace->GetData()._spaceType == NLogic::Space::SpaceType::PVP_PRACTICE)
	{
		int winUserSeq = pSpace->GetData()._winnerGID;
		pWinUser = pSpace->FindUser(winUserSeq);
	}
	else
	{
		if (pSpace->GetData()._winnerGID == static_cast<int>(pUser->GetUserSeq()))
			pWinUser = pUser;
		else
			pWinUser = pUser->GetBattle()->GetData()._pvpOppUser;
	}


	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << static_cast<int16_t>(res);
	*pAck << static_cast<uint32_t>(winPoint);			// 승점
	*pAck << static_cast<uint16_t>(pUser->GetCharacterInfo().ep_current);
	*pAck << static_cast<uint16_t>(pUser->GetCharacterInfo().ep_max);
	*pAck << static_cast<int16_t>(evolvePoint);
	*pAck << itemSeq;
	*pAck << static_cast<uint8_t>(bagType);

	if (pWinUser == NULL)		// AI 대전
		*pAck << static_cast<int16_t>(0);
	else
		*pAck << pWinUser->GetCharacterInfo().win_comment.c_str();

	DEBUGLOG("##### CS_GET_MATCH_RESULT : userseq=%d, winpoint=%d, evolvepoint=%d", pUser->GetUserSeq(), winPoint, evolvePoint);

	pAck->MakePacket(CMD_SC_GET_MATCH_RESULT);
	pUser->Send(pAck);

	// 이벤트 로그 기록
	NGameLog::LaunchingEvent(pUser, 1);
}

void Command::CS_GET_MATCH_RESULT(User * pUser, ::Network::Packet * pPacket)
{
/*	/// 대전 결과 요청
	CS_GET_MATCH_RESULT				0x1309
	{

	}

	SC_GET_MATCH_RESULT				0x130a
	{
		s16				s16ack;
		u32				u32reward_score;				//승점
		u16				u16reward_ev_point;				//진화포인트(증차감 끝난값)
		u16				u16reward_ev_point_max;			//자신의 진화 MAX 값
		s16				s16reward_ev_point_variation;	//증차감 시킬 진화 포인트
		u64				u64item_seq;					//아이템 seq (0 이면 보상아이템 없음)
		u8				u8bag_type;
		str				strpvp_win_message;				//승리한 유저의 승리 메세지
	}*/

	PREPARE_PACKET;

	NLogic::Space * pSpace	= pUser->GetSpace();

	if (pSpace == NULL)
	{
		DEBUGLOG("CS_GET_MATCH_RESULT : pSpace is NULL!! userseq=%d", pUser->GetUserSeq());
		return;
	}

	if (pSpace->GetData()._spaceType != NLogic::Space::SpaceType::PVP_USER
			&& pSpace->GetData()._spaceType != NLogic::Space::SpaceType::PVP_PRACTICE
			&& pSpace->GetData()._spaceType != NLogic::Space::SpaceType::NEW_PVP_ROOM)
	{
		DEBUGLOG("CS_GET_MATCH_RESULT : Spacetype is Not PVP!!");
		return;
	}

	if (true == pUser->GetBattle()->GetData()._pvpReward)
	{
		DEBUGLOG("CS_GET_MATCH_RESULT true == pUser->GetBattle()->GetData()._pvpReward");
		return;
	}

	// PVP 대전이 종료되는 시점에 지연 유저가 있으면 Space에서 제거
	if (pSpace->GetData()._spaceType == NLogic::Space::SpaceType::PVP_USER
			|| pSpace->GetData()._spaceType == NLogic::Space::SpaceType::NEW_PVP_ROOM)
	{
		NLogic::Party * pParty = pSpace->GetParty();

		if (pParty == NULL)
		{
			DEBUGLOG("CS_GET_MATCH_RESULT : pParty is NULL!! userseq=%d", pUser->GetUserSeq());
			return;
		}

		// 상대가 AI 유저인 경우 Space에서 제거한다
		User * pOppUser = pUser->GetBattle()->GetData()._pvpOppUser;

		if (NULL != pOppUser && true == pParty->IsPVPDelayUser(pOppUser) && NULL != pSpace->FindUser(pOppUser->GetUserSeq()))
		{
			pSpace->LeaveUser(pOppUser);

			pOppUser->GetBattle()->GetData().x		= ConstPosX;
			pOppUser->GetBattle()->GetData().y		= ConstPosY;
			pOppUser->GetBattle()->GetData().degree = ConstDegree;
			pOppUser->GetBattle()->GetData().bReadyFight = false;
			pOppUser->GetBattle()->GetData().bRecvEnterRoom = false;

			::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

			*pAck << static_cast<int16_t>(ACK_PVP_PK_NOT_EXIST_ROOM);
			*pAck << pOppUser->GetUserSeq();
			*pAck << static_cast<uint16_t>(1);			// exit_map_id(?)
			*pAck << static_cast<uint16_t>(pOppUser->GetBattle()->GetData().x);
			*pAck << static_cast<uint16_t>(pOppUser->GetBattle()->GetData().y);
			*pAck << static_cast<uint16_t>(pOppUser->GetBattle()->GetData().degree);

			pAck->MakePacket(CMD_SC_PVP_OUT_REQ);
			pOppUser->Send(pAck);
		}
	}

	// 연습 대전인 경우 무조건 승점 1 획득
	if (pSpace->GetData()._spaceType == NLogic::Space::SpaceType::PVP_PRACTICE)
	{
		int winPoint = 0;

		if (pSpace->GetData()._winnerGID == static_cast<int>(pUser->GetUserSeq()))
		{
			winPoint = 1;

			// 연승 정보
			pUser->GetCharacterInfo().consecutive_win += 1;

			pUser->GetUserInfo().wp_cur_week += winPoint;
			pUser->GetUserInfo().wp_reg_date = time(NULL);

			// 승점 데이터 Memcache 반영
			pUser->GetScore()->SetMemcache();
			pUser->GetScore()->SetRedis(winPoint);
		}
		else
		{
			// AI 대전 패배인 경우 연승 정보 초기화
			pUser->GetCharacterInfo().consecutive_win = 0;
		}

		SendPacket_CS_GET_MATCH_RESULT(pUser, pSpace, ACK_OK, winPoint, 0, 0, 0);
		pUser->GetBattle()->GetData()._pvpReward = true;

		// 일일 미션
		NLogic::DailyMission * pDailyMission = pUser->GetDailyMission();
		if (NULL != pDailyMission)
		{
			pDailyMission->MissionComplete(NLogic::DailyMission::MissionType::MISSION3);
		}

		return;
	}




	// 연승 정보
	bool bWin	= false;
	if (pSpace->GetData()._winnerGID == static_cast<int>(pUser->GetUserSeq()))
	{
		pUser->GetCharacterInfo().consecutive_win += 1;
		bWin = true;
	}
	else
	{
		pUser->GetCharacterInfo().consecutive_win = 0;
	}

	NLogic::BattleResult::Data & clsData = pUser->GetBattleResult()->GetData();

	int evolvePoint	= bWin ? clsData.winEP : clsData.loseEP;
	int winPoint	= bWin ? clsData.winWP : clsData.loseWP;

//	// 진화포인트 반영
//	int ep_current = pUser->GetCharacterInfo().ep_current + evolvePoint;
//
//	if (ep_current < 0)
//	{
//		ep_current = 0;
//	}
//	else if (ep_current > static_cast<int>(pUser->GetCharacterInfo().ep_max))
//	{
//		ep_current = pUser->GetCharacterInfo().ep_max;
//	}
//
//	pUser->GetCharacterInfo().ep_current = ep_current;

	// 승점 반영
	int wp_current = pUser->GetUserInfo().wp_cur_week + winPoint;

	if (wp_current < 0)
	{
		wp_current = 0;
	}

	pUser->GetUserInfo().wp_cur_week = wp_current;
	pUser->GetUserInfo().wp_reg_date = time(NULL);

	// 승점 데이터 Memcache 반영
	pUser->GetScore()->SetMemcache();
	pUser->GetScore()->SetRedis(winPoint);

	int ackReturn		= ACK_OK;
	uint64_t itemSeq	= 0;

	// 승자만 PVP 보상
	if (true == bWin && 0 <= clsData.itemData.bag_type)
	{
		NLogic::Bag * pBag = pUser->GetBag(static_cast<INVEN_BAG_TYPE>(clsData.itemData.bag_type));
		if (pBag == NULL)
		{
			DEBUGLOG("CS_GET_MATCH_RESULT : pBag is NULL!!");
			SendPacket_CS_GET_MATCH_RESULT(pUser, pSpace, ACK_UNKNOWN_ERROR, 0, 0, 0, 0);
			return;
		}

		bool bBagFull = false;
		NLogic::Item * pItem = pBag->AddItemWithData(clsData.itemData, bBagFull);

		if (NULL == pItem)
		{
			// 인벤토리가 꽉 찬 경우 메일로 발송
			if (true == bBagFull)
			{
				ackReturn = ACK_INVEN_FULL_SEND_MAIL;

				NLogic::MailBox::Mail::Data clsMailData;

				clsMailData.send_user_seq		= 0;
				clsMailData.send_user_nickname	= "GAMEVIL";
				clsMailData.recv_user_seq		= pUser->GetUserSeq();
				clsMailData.gift_status			= EM_GIFT_ITEM;
				clsMailData.item				= clsData.itemData;
				clsMailData.message				= NResource::Static::InstancePtr()->GetMailMessageResource()->GetMessagePVPWinReward();

				// 아이템 부가 정보 설정
				NResource::Static::InstancePtr()->GetItemResource()->SetItemDataFromResource(pUser, clsMailData.item);

				if (false == NLogic::NFunction::SendMail(pUser, clsMailData))
				{
					DEBUGLOG("CS_GET_MATCH_RESULT : false == NLogic::NFunction::SendMail");
					return;
				}
			}
			else
			{
				DEBUGLOG("CS_GET_MATCH_RESULT : pItem is NULL!!");
				return;
			}
		}
		else
		{
			itemSeq = pItem->GetItemSeq();
		}
	}

	time_t curtime = time(NULL);
	::ProjectZ::NGameLog::Bson * pBson = ::ProjectZ::NGameLog::Static::Instance().GETBSONPOOL()->NEW();
	if(NULL != pBson)
	{
		pBson->SetCollections("log_pvp_play");
		bson * bson = pBson->GetBsonData();
		bson_append_int( bson, "user_seq", pUser->GetUserSeq() );
		bson_append_int( bson, "company", pUser->GetCompany() );
		bson_append_int( bson, "sale_code", pUser->GetSaleCode() );
		bson_append_int( bson, "character_class", pUser->GetCharacterInfo().classtype );
		bson_append_int( bson, "character_level", pUser->GetCharacterInfo().level );

		bson_append_int( bson, "enermy_user_seq", pUser->GetBattle()->GetData()._pvpOppUser->GetUserSeq() );
		bson_append_int( bson, "enermy_company", pUser->GetBattle()->GetData()._pvpOppUser->GetCompany() );
		bson_append_int( bson, "enermy_sale_code", pUser->GetBattle()->GetData()._pvpOppUser->GetSaleCode() );
		bson_append_int( bson, "enermy_character_class", pUser->GetBattle()->GetData()._pvpOppUser->GetCharacterInfo().classtype );
		bson_append_int( bson, "enermy_character_level", pUser->GetBattle()->GetData()._pvpOppUser->GetCharacterInfo().level );

		bson_append_int( bson, "space_num", pSpace->GetData()._index );
		bson_append_time_t( bson, "start_time", pSpace->GetData()._starttick );
		bson_append_time_t( bson, "end_time", curtime );
		bson_append_int( bson, "play_time", curtime - pSpace->GetData()._starttick );
		bson_append_int( bson, "item_seq", itemSeq );
		bson_append_int( bson, "win_point", winPoint );
		bson_append_time_t( bson, "reg_time", curtime );

		::ProjectZ::NGameLog::MongoDB * pMongoDB = ::ProjectZ::NGameLog::Static::Instance().GetMongoDB();
		pMongoDB->Push(pBson);
	}

	// 응답
	SendPacket_CS_GET_MATCH_RESULT(pUser, pSpace, ackReturn, winPoint, evolvePoint, itemSeq, clsData.itemData.bag_type);

	pUser->SetEnumState(User::EnumState::PVP_BATTLE_END);

	pUser->GetBattle()->GetData()._pvpReward = true;

	// 일일 미션
	NLogic::DailyMission * pDailyMission = pUser->GetDailyMission();
	if (NULL != pDailyMission)
	{
		pDailyMission->MissionComplete(NLogic::DailyMission::MissionType::MISSION3);
	}

	// 길드 포인트 반영
	NProxy::ApplyGuildPoint(pUser, 2, bWin);
}

} /*NCommand*/ } /*ProjectZ*/
